/**
 * This file is Copyright © 2008 Software Craftsmen Limited. All Rights Reserved.
 */
package com.softwarecraftsmen.orogeny.filing.absolutePathMetaData.posixIdentifiers;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import static java.lang.String.format;
import static java.util.Locale.UK;

public abstract class AbstractPosixIdentifier implements PosixIdentifier
{
	@NotNull
	protected static final String RootUserName = "root";
	protected static final long BestGuessIdentifier = 1000;

	private static final long MaximumIdentifier = 4294967295l;
	private final long identifier;
	private final String name;
	private final boolean unknown;

	protected AbstractPosixIdentifier(final long identifier, final @NotNull String name, final boolean unknown)
	{
		this.unknown = unknown;
		if (!unknown && identifier < 0)
		{
			throw new IllegalArgumentException(format(UK, "Negative identifiers, such as %1$s, are not allowed. Unix identifiers are unsigned 32 bit quantities", identifier));
		}
		if (identifier >= MaximumIdentifier)
		{
			throw new IllegalArgumentException(format(UK, "Identifiers, such as %1$s, are not allowed. Unix identifiers are unsigned 32 bit quantities", identifier));
		}
		if (name.isEmpty())
		{
			throw new IllegalArgumentException("Empy names are not allowed");
		}
		if (name.length() > 31)
		{
			throw new IllegalArgumentException(format(UK, "name can not be longer than 31 characters. %1$s is longer", name));
		}
		this.identifier = identifier;
		this.name = name;
	}

	public final long identifier()
	{
		return identifier;
	}

	@NotNull
	public final String name()
	{
		return name;
	}

	public boolean unknown()
	{
		return unknown;
	}

	public boolean equals(final @Nullable Object o)
	{
		if (this == o)
		{
			return true;
		}
		if (o == null || getClass() != o.getClass())
		{
			return false;
		}

		final AbstractPosixIdentifier that = (AbstractPosixIdentifier) o;
		return identifier == that.identifier && unknown == that.unknown && name.equals(that.name);
	}

	public int hashCode()
	{
		int result;
		result = (int) (identifier ^ (identifier >>> 32));
		result = 31 * result + name.hashCode();
		result = 31 * result + (unknown ? 1 : 0);
		return result;
	}

	@NotNull
	public String toString()
	{
		return name;
	}
}
